8. Visualização de dados

1 Diretório

2 Pacotes e dados

library(rio)
library(tidyverse)
library(metan)

# set_wd_here("data")
# dados
df <- import("eucalipto.xlsx")
df_retangulo <- 
  df |> 
  mutate(col = rep(1:14, 5),
         row = rep(1:5, each = 14))

3 Gráficos

“O gráfico simples trouxe mais informações à mente do analista de dados do que qualquer outro dispositivo.” — John Tukey

3.1 O pacote ggplot2

O ggplot2 é um pacote R para produção de gráficos que diferentemente da maioria dos outros pacotes, apresenta uma profunda gramática baseada no livro The grammar of graphics (Wilkinson 2005)1. Os gráficos originados em ggplot2 são baseados em camadas, e cada gráfico tem três componentes chave: data, os dados de onde o gráfico será criado; aes() (aesthetic mappings), que controla o mapeamento estético e as propriedades visuais do gráfico; e ao menos uma camada que irá descrever como cada observação será renderizada. Camadas são usualmente criadas utilizando uma função geom_().

3.2 Galerias

  • https://www.r-graph-gallery.com/portfolio/ggplot2-package/
  • http://r-statistics.co/Top50-Ggplot2-Visualizations-MasterList-R-Code.html
  • https://r4stats.com/examples/graphics-ggplot2/
  • http://girke.bioinformatics.ucr.edu/GEN242/pages/mydoc/Rgraphics.html

3.3 Extensões do ggplot2

  • http://www.ggplot2-exts.org/gallery/
  • https://mode.com/blog/r-ggplot-extension-packages

3.4 Tutoriais em português

  • https://rpubs.com/mnunes/ggplot2
  • https://analisereal.com/2015/09/19/introducao-ao-ggplot2/
  • https://timogrossenbacher.ch/2016/12/beautiful-thematic-maps-with-ggplot2-only/
  • http://recologia.com.br/tag/graficos/
  • http://rstudio-pubs-static.s3.amazonaws.com/24563_3b7b0a6414824e3b91769a95309380f1.html
  • http://eduardogutierres.com/inteligencia-geografica-gerando-mapas-em-r/
  • https://pt.stackoverflow.com/questions/332053/r-mapa-de-cidades-brasileiras

3.5 Meu primeiro gráfico em ggplot2

A seguir, vamos discutir os aspcetos básicos para a construção de gráficos utilizando o pacote ggplot2. A função arrange_ggplot() do pacote metan é utilizada aqui para organizar os gráficos em forma de painéis.

3.6 As camadas de um gráfico ggplot2

No ggplot2, os gráficos são construídos camada por camada (ou, layers, em inglês). Neste exemplo, vamos confeccionar um gráfico mostrando a distribuição do dap_suta da folha (eixo x) e circunferencia da folha (eixo y).

p1 <- 
  ggplot(df, aes(x = dap_suta, y = circunferencia)) +
  geom_point()
p1

Este comando criou um gráfico e armazenou no objeto p1, que será plotado posteriormente. Observe que o primeiro argumento da função é o data frame onde nossos dados foram armazenados. A função aes() descreve como as variáveis são mapeadas (neste caso dap_suta no eixo x e circunferencia no eixo y). A função geom_point() definiu que a forma geométrica a ser utilizada é baseada em pontos, gerando, assim, um gráfico de dispersão. Isto é tudo que precisa ser feito para a confecção de um gráfico simples.

3.7 Aesthetics (estética)

“O maior valor de uma imagem é quando ela nos obriga a perceber o que nunca esperamos ver.” — John Tukey

Alterar a estética dos gráficos ggplot2 é uma tarefa relativamente simples. No gráfico anterior, os valores do dap_suta e circunferencia foram plotados sem nenhum tipo de mapeamento estético. Digamos que marcadores com diferentes cores para cada nível do fator fila poderia nos ajudar a compreender melhor o padrão presente em nossos dados. Vamos confeccionar este gráfico.

p2 <- 
  ggplot(df, aes(x = dap_suta, y = circunferencia, color = fila)) +
  geom_point()
p2

Ao incluirmos color = fila dentro da função aes, dizemos ao ggplot que os pontos devem ser mapeados esteticamente (neste caso utilizando cores) para cada nível do fator fila presente em nossos dados. Digamos que em vez de utilizar diferentes cores, cada fila deveria ser representada por diferentes tipos de marcadores (quadrados, triângulo, etc.) Neste caso, o argumento colour = fila é substituído por shape = fila.

p3 <- 
  ggplot(df, aes(x = dap_suta, 
                 y = circunferencia,
                 shape = fila)) +
  geom_point()


# organizar os gráficos
arrange_ggplot(p1, p2, p3,
               ncol = 3,
               tag_levels = list(c("p1", "p2", "p3")))

3.8 Salvar gráficos

A função ggsave() é uma função conveniente para salvar um gráfico. O padrão é salvar a última plotagem exibida, usando o tamanho do dispositivo gráfico atual. Também é possível informar a altura (height) e circunferencia (width). Ele também adivinha o tipo de dispositivo gráfico da extensão. No seguinte exemplo, o gráfico acima é salvo no diretório de trabalho atual com o nome pontos.png, com 5 polegadas de altura e 10 de circunferencia.

ggsave("pontos.png",
       height = 5,
       width = 10)

3.9 Facet (facetas)

Mapeando os diferentes níveis de cor para diferentes cores, incluímos em um único gráfico os dados de todos osgrupos. Mas, e se nosso objetivo fosse realizar um gráfico para cada grupo? O ggplot2 tem uma poderosa ferramenta para isto: as funções facet_. Ao utilizar estas funções, o conjunto de dados é subdividido e um gráfico é construído para cada um destes subconjuntos. Vamos ver como elas podem nos ajudar em nosso problema.

fac1 <- 
  ggplot(df, aes(x = dap_suta,
                 y = circunferencia,
                 color = fila)) +
  geom_point() +
  facet_wrap(~ fila, ncol = 5)
fac1

Um painel para cada nível da variável grupo.

Neste exemplo, um gráfico completamente diferente do anterior é gerado com apenas uma simples adição: incluímos uma nova função, facet_wrap(~ fila). Neste caso, informamos que um gráfico deveria ser realizado para cada grupo.

3.10 Theme (temas)

Cada gráfico criado com a função ggplot() tem um tema padrão. Tema, aqui, é toda propriedade relacionada ao aspecto visual do gráfico, que não foi definida na função aes() e que pode ser modificada utilizando a função theme() (veja ?theme). O ggplot2 já conta com alguns temas personalizados para facilitar nosso trabalho. Considerando o exemplo anterior, vamos utilizar a função theme_bw() (preto e branco) e a função theme() para modificar as propriedades visuais do gráfico.

fac2 <- 
  ggplot(df, aes(x = dap_suta, y = circunferencia, color = fila)) +
  geom_point() +
  facet_wrap(~ fila) +
  theme_light() +
  theme(panel.grid.minor = element_blank(), # remove as linhas do corpo do gráfico
        # sem bordas entre os painéis
        panel.spacing = unit(0, "cm"),
        # legenda abaixo do gráfico
        legend.position = "bottom",
        # modifica o texto dos eixos
        axis.text = element_text(size = 12, colour = "black"),
        # cor dos marcadores
        axis.ticks = element_line(colour = "black"),
        # tamanho dos marcadores
        axis.ticks.length = unit(.2, "cm"))+
  # título dos eixos
  labs(x = "Diâmetro a altura do peito (cm)", # título do eixo x
       y = "Circunferência", # título do eixo y
       color = "") # título da legenda

arrange_ggplot(fac1, fac2,
               ncol = 1,
               tag_levels = list(c("f1", "f2")))

Gráfico de dispersão considerando a confecção de um gráfico para cada nível de um fator(f1) e modificações na propriedades do tema de um gráfico ggplot2 (f2)

Os argumentos inseridos dentro das função theme() modificaram a aparência do nosso gráfico. Inúmeros outros argumentos são disponíveis, fazendo com que os gráficos originados sejam completamente personalizáveis. Digamos que precisamos confeccionar diversos gráficos e gostaríamos de manter o mesmo tema do gráfico acima. Seria exaustivo e desinteressante informar cada vez estes argumentos para cada gráfico, não? Felizmente, outra poderosa ferramenta proporcionada pelo ggplot2 é a possibilidade de confeccionarmos nossos próprios temas. Para isto, vamos executar o seguinte comando para criar um tema personalizado (my_theme()). Este tema pode então ser aplicado como uma camada adicional a cada gráfico que confecionarmos. Para evitar a necessidade da inclusão deste tema em cada gráfico gerado, iremos definir este tema como padrão utilizando a função theme_set().

my_theme <- function () {
  theme_light() %+replace% # permite que os valores informados possam ser sobescritos
    theme(axis.ticks.length = unit(.2, "cm"),
          axis.text = element_text(size = 12, colour = "black"),
          axis.title = element_text(size = 12, colour = "black"),
          axis.ticks = element_line(colour = "black"),
          panel.border = element_rect(colour = "black", fill = NA, size = 0.5),
          panel.grid.minor =  element_blank())
}
theme_set(my_theme())

3.11 Geoms (geometria)

As funções geom_ definem qual forma geométrica será utilizada para a visualização dos dados no gráfico. Até agora, utilizamos a função geom_point()para construir gráficos de dispersão. Basicamente, qualquer outro tipo de gráfico pode ser criado dependendo da função geom_ utilizada. Dentre as diversas disponíveis no pacote ggplot2 as funções geom_ mais utilizadas são:

Deste ponto em diante, vamos confeccionar alguns exemplos utilizando algumas destas funções (ou combinações destas funções) incluindo argumentos de mapeamento de estética e temas vistos até agora.

3.11.1 Linhas horizontais, verticais e diagonais

Três importantes geometrias são apresentadas a seguir:

  1. geom_hline() adiciona uma linha horizontal definida por um intercepto em y

  2. geom_vline() adiciona uma linha vertical definida por um intercepto em x.

  3. geom_abline() adiciona uma linha diagonal definida por um intercepto e uma inclinação.

g1 <- 
  ggplot(df, aes(dap_suta, circunferencia)) +
  geom_point()
g1

# adiciona linhas horizontais e verticais
g2 <- 
  g1 +
  geom_hline(yintercept = mean(df$circunferencia), color = "blue") +
  geom_vline(xintercept = mean(df$dap_suta), color = "red") +
  geom_smooth(method = "lm", se = FALSE)

arrange_ggplot(g1, g2,
               ncol = 1,
               tag_levels = list(c("g1", "g2")))
`geom_smooth()` using formula = 'y ~ x'

3.11.2 Gráficos do tipo boxplot

box1 <- 
  ggplot(df, aes(fila, dap_suta)) +
  geom_boxplot()

box2 <- 
  ggplot(df, aes(fila, dap_suta)) +
  geom_boxplot(outlier.colour = "transparent") +
  geom_jitter(width = 0.1, color = "salmon")

box3 <- 
  ggplot(df, aes(fila, dap_suta, fill = fila)) +
  geom_boxplot(width = 0.3) + 
  labs(x = "Grupo",
       y = "dap_suta do grão (mm)") +
  theme(legend.position = "bottom")

arrange_ggplot((box1 + box2) / box3,
               tag_levels = list(c("b1", "b2", "b3")))

Gráfico do tipo boxplot combinando mapeamentos estéticos.

Cinco estatísticas são mostradas neste boxplot. A mediana (linha horizontal), as caixas inferior e superior (primeiro e terceiro quartil (percentis 25 e 75, respectivamente)). A linha vertical superior se estende da caixa até o maior valor, não maior que $1,5 $ (onde IQR é a amplitude interquartílica). A linha vertical inferior se estende da caixa até o menor valor, de no máximo, $1,5 $. Dados além das linhas horizontais podem ser considerados outliers.

3.11.3 Gráficos do tipo barra

No seguinte exemplo, os dados do dap_suta do grão de café disponíveis em df são utilizados.

bar1 <- 
  ggplot(df, aes(x = fila, y = dap_suta)) +
  geom_bar(stat = "summary", fun = "mean")

bar2 <- 
  ggplot(df, aes(x = fila, y = dap_suta, fill = fila)) +
  stat_summary(fun = mean,
               geom = "bar",
               col = "black",
               width = 0.8,
               position = position_dodge(0.8)) + 
  stat_summary(fun.data = mean_se,
               geom = "errorbar",
               width = 0.2,
               position = position_dodge(0.8))


arrange_ggplot(bar1, bar2,
               widths = c(0.6, 1.2),
               tag_levels = list(c("bar1", "bar2")))

Gráfico do tipo barras, com mapeamento estético e barras de erro.

A afirmação de que um gráfico ggplot2 é feito em camadas fica mais evidente aqui. No gráfico bar1, as barras representam as médias geral do dap_suta para cada grupo. No segundo gráfico, ao usar fill = fila informamos que as barras devem ser coloridas para cada nível do fator fila. A função stat_summary(), é vista pela primeira vez aqui, foi utilizada no segundo gráfico para substituir a função geom_bar(). Com isto, foi possível incluir as médias (fun = mean e geom = "bar), bem como as barras de erro (fun.data = mean_se e geom = "errorbar").

3.11.4 Gráficos do tipo histograma e densidade

h1 <- 
  ggplot(df, aes(x = circunferencia)) +
  geom_histogram()

d1 <- 
  ggplot(df, aes(x = circunferencia)) +
  geom_density()

arrange_ggplot(h1, d1,
               widths = c(1, 1.4),
               tag_levels = list(c("h1", "h2")))

Gráfico do tipo histograma

3.12 Mapas

3.12.1 Mapa da américa do sul e Brasil

O pacote rnaturalearth é uma excelente ferramenta para manter e facilitar a interação com os dados do mapa Natural Earth. Para produção de mapas com o ggplot2, os seguintes pacotes são necessários.

#| out-width: "100%"


# américa do sul
library(rnaturalearth)
library(tidyverse)
sam <-
  ne_countries(continent = "south america",
               returnclass = "sf",
               scale = 50)

p1 <- 
  ggplot() +
  geom_sf(data = sam, fill = "white") +
  theme_light() +
  xlim(c(-90, -35))

# plotar o brasil e destacar santa catarina
brazil <- 
  ne_states(country = "brazil", returnclass = "sf") |> 
  mutate(scat = ifelse(postal == "PR", "PR", "Outros"))

p2 <- 
  p1 + 
  geom_sf(data = brazil, aes(fill = scat))
p2

3.12.2 Mapa do Brasil e SC, com municípios

library(geobr)


pr <- 
  read_municipality(code_muni = "PR",
                    simplified = FALSE,
                    showProgress = FALSE) |> 
  mutate(Curitiba = ifelse(name_muni == "Curitiba",
                          "Curitiba",
                          "Outro"))
Using year/date 2010
p3 <-
  p1 + 
  geom_sf(data = brazil) +
  geom_sf(data = pr, aes(fill = Curitiba)) +
  xlim(c(-55, -47)) +
  ylim(c(-28, -22)) +
  labs(title = "Mapa do brasil destacando o estado de SC",
       caption = "Produzido com os pkgs geobr e rnaturalearth",
       fill = "") +
  theme(legend.position = "bottom")
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.
p3

Footnotes

  1. WICKHAM, H. Ggplot2 : elegant graphics for data analysis: Springer, 2009.↩︎